package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.GlobalListener.GlobalFinishListener;
import com.ruoyi.system.GlobalListener.GlobalStartListener;
import com.ruoyi.system.domain.TestLeave;
import com.ruoyi.system.mapper.TestLeaveMapper;
import com.ruoyi.system.service.ISysDictTypeService;
import com.ruoyi.system.service.ITestLeaveService;
import com.warm.flow.core.FlowFactory;
import com.warm.flow.core.dto.FlowParams;
import com.warm.flow.core.entity.Instance;
import com.warm.flow.core.enums.SkipType;
import com.warm.flow.core.service.InsService;
import com.warm.flow.core.service.TaskService;
import com.warm.flow.core.utils.CollUtil;
import com.warm.flow.core.utils.IdUtils;
import com.warm.flow.core.utils.StreamUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * OA 请假申请Service业务层处理
 *
 * @author ruoyi
 * @date 2024-03-07
 */
@Service
public class TestLeaveServiceImpl implements ITestLeaveService
{
    @Resource
    private TestLeaveMapper testLeaveMapper;

    @Resource
    private InsService insService;

    @Resource
    private TaskService taskService;

    @Resource
    private ISysDictTypeService sysDictTypeService;

    /**
     * 查询OA 请假申请
     *
     * @param id OA 请假申请主键
     * @return OA 请假申请
     */
    @Override
    public TestLeave selectTestLeaveById(String id)
    {
        TestLeave testLeave = testLeaveMapper.selectTestLeaveById(id);
        List<String> permission = FlowFactory.userService().getPermission(testLeave.getInstanceId(), "4");
        if (CollUtil.isNotEmpty(permission)) {
            testLeave.setAdditionalHandler(permission);
        }else {
            testLeave.setAdditionalHandler(new ArrayList<>());
        }
        return testLeave;
    }

    /**
     * 查询OA 请假申请列表
     *
     * @param testLeave OA 请假申请
     * @return OA 请假申请
     */
    @Override
    public List<TestLeave> selectTestLeaveList(TestLeave testLeave)
    {
        return testLeaveMapper.selectTestLeaveList(testLeave);
    }

    /**
     * 新增OA 请假申请
     *
     * @param testLeave OA 请假申请
     * @return 结果
     */
    @Override
    public int insertTestLeave(TestLeave testLeave, String flowStatus)
    {
        String id = IdUtils.nextIdStr();
        testLeave.setId(id);
        FlowParams flowParams = FlowParams.build().flowCode(getFlowType(testLeave));
        // 流程变量
        Map<String, Object> variable = new HashMap<>();
        variable.put("businessData", testLeave);
        variable.put("flag", String.valueOf(testLeave.getDay()));
        variable.put("handler1", "100");
        variable.put("handler2", "101");
        flowParams.variable(variable);
        // 自定义流程状态扩展
        if (StringUtils.isNotEmpty(flowStatus)) {
            flowParams.flowStatus(flowStatus).hisStatus(flowStatus);
        }

        Instance instance = insService.start(id, flowParams);
        return instance != null? 1 : 0;
    }

    /**
     * 修改OA 请假申请
     *
     * @param testLeave OA 请假申请
     * @return 结果
     */
    @Override
    public int updateTestLeave(TestLeave testLeave)
    {
        testLeave.setUpdateTime(DateUtils.getNowDate());
        return testLeaveMapper.updateTestLeave(testLeave);
    }

    /**
     * 批量删除OA 请假申请
     *
     * @param ids 需要删除的OA 请假申请主键
     * @return 结果
     */
    @Override
    public int deleteTestLeaveByIds(String[] ids)
    {
        List<TestLeave> testLeaveList = testLeaveMapper.selectTestLeaveByIds(ids);
        if (testLeaveMapper.deleteTestLeaveByIds(ids) > 0) {
            List<Long> instanceIds = testLeaveList.stream().map(TestLeave::getInstanceId).collect(Collectors.toList());
            return insService.remove(instanceIds) ? 1: 0;
        }
        return 0;
    }

    /**
     * 删除OA 请假申请信息
     *
     * @param id OA 请假申请主键
     * @return 结果
     */
    @Override
    public int deleteTestLeaveById(String id)
    {
        return testLeaveMapper.deleteTestLeaveById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int submit(String id, String flowStatus) {
        TestLeave testLeave = testLeaveMapper.selectTestLeaveById(id);
        FlowParams flowParams = FlowParams.build().skipType(SkipType.PASS.getKey());
        /** 设置办理人id、所拥有的权限等操作，可在此处设置, 本案例放在全局全局开始监听器中{@link GlobalStartListener}*/

        // 自定义流程状态扩展
        if (StringUtils.isNotEmpty(flowStatus)) {
            flowParams.flowStatus(flowStatus).hisStatus(flowStatus);
        }
        // 流程变量
        Map<String, Object> variable = new HashMap<>();
        variable.put("businessData", testLeave);
        variable.put("flag", String.valueOf(testLeave.getDay()));
        flowParams.variable(variable);

        Instance instance = insService.skipByInsId(testLeave.getInstanceId(), flowParams);
        /** 业务表新增或者更新操作，可在此处设置, 本案例放在全局完成监听器中{@link GlobalFinishListener}*/

        return instance != null? 1 : 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int handle(TestLeave testLeave, Long taskId, String skipType, String message, String nodeCode, String flowStatus) {
        // 设置流转参数
        FlowParams flowParams = FlowParams.build()
                .skipType(skipType)
                .nodeCode(nodeCode)
                .message(message);
        /** 设置办理人id、所拥有的权限等操作，可在此处设置, 本案例放在全局开始监听器中{@link GlobalStartListener}*/
        // 流程变量
        Map<String, Object> variable = new HashMap<>();
        variable.put("businessData", testLeave);
        variable.put("flag", String.valueOf(testLeave.getDay()));
        flowParams.variable(variable);
        // 自定义流程状态扩展
        if (StringUtils.isNotEmpty(flowStatus)) {
            flowParams.flowStatus(flowStatus).hisStatus(flowStatus);
        }
        // 请假信息存入flowParams
        flowParams.hisTaskExt(JSON.toJSONString(testLeave));
        Instance instance = taskService.skip(taskId, flowParams);
        /** 业务表新增或者更新操作，可在此处设置, 本案例放在全局完成监听器中{@link GlobalFinishListener}*/

        return instance != null? 1 : 0;
    }

    @Override
    public int termination(TestLeave testLeave) {
        Map<String, Object> variable = new HashMap<>();
        variable.put("businessData", testLeave);
        FlowParams flowParams = new FlowParams().variable(variable).message("终止流程");
        /** 设置办理人id、所拥有的权限等操作，可在此处设置, 本案例放在全局开始监听器中{@link GlobalStartListener}*/
        Instance instance = insService.termination(testLeave.getInstanceId(), flowParams);
        /** 业务表新增或者更新操作，可在此处设置, 本案例放在全局完成监听器中{@link GlobalFinishListener}*/

        return instance != null? 1 : 0;
    }

    private String  getFlowType(TestLeave testLeave) {
        List<SysDictData> leaveType = sysDictTypeService.selectDictDataByType("leave_type");
        Map<String, String> map = StreamUtils.toMap(leaveType, SysDictData::getDictValue, SysDictData::getRemark);
        return map.get(testLeave.getType().toString());
    }

}
